using UnityEngine;

[RequireComponent(typeof(Rigidbody))]
public class GOdrive : MonoBehaviour
{
	[SerializeField]
	public float topSpeedMPH = 85f;

	[SerializeField]
	public float accelTime = 3f;

	[SerializeField]
	public float traction = 0.7f;

	[SerializeField]
	public Transform frontLeftWheelTransform;

	[SerializeField]
	public Transform frontRightWheelTransform;

	[SerializeField]
	public Transform rearLeftWheelTransform;

	[SerializeField]
	public Transform rearRightWheelTransform;

	[SerializeField]
	public float maximumSteeringAngle = 40f;

	[SerializeField]
	public float offTrackDragMultiplier = 2f;

	private float thrust;

	private float steer;

	private float currentMPH;

	private bool isGrounded = true;

	private bool isOffTrack;

	private Rigidbody physicsBody;

	private WheelCollider wheelCollider;

	private WheelCollider wheelColliderFrontRight;

	private WheelCollider wheelColliderFrontLeft;

	private WheelCollider wheelColliderRearRight;

	private WheelCollider wheelColliderRearLeft;

	private GameObject steerRightFront;

	private GameObject steerLeftFront;

	private GameObject steerOneWheel;

	private Vector3 myDrag;

	private Vector3 myLocalVelocity;

	private Vector3 myGlobalVelocity;

	private Vector3 myWheelRayCastLocation;

	private Vector3 myWheelRayCastLocationFront;

	private Vector3 myWheelRayCastLocationRear;

	private float myFrontWheelRadius;

	private float myRearWheelRadius;

	private float wheelRotationFront;

	private float steerAngle;

	private float tempSpeedVariable;

	private float myCalculatedThrust;

	private float myAirMomentum;

	private float thrust_myAirMomentum;

	private float thrust_CurrentVelocity;

	private bool buildingMomentum;

	private bool buildingReverseMomentum;

	private float accelerationTime;

	private float accel;

	private RaycastHit hit;

	public float Thrust
	{
		get
		{
			return thrust;
		}
		set
		{
			thrust = Mathf.Clamp(value, -1f, 1f);
		}
	}

	public float Steering
	{
		get
		{
			return steer;
		}
		set
		{
			steer = Mathf.Clamp(value, -1f, 1f);
		}
	}

	public float MPH => currentMPH;

	public bool IsGrounded => isGrounded;

	public bool IsOffRoad => isOffTrack;

	private void Start()
	{
		physicsBody = GetComponent<Rigidbody>();
		physicsBody.centerOfMass = Vector3.up * -0.25f;
		wheelColliderFrontLeft = base.transform.Find("WheelColliders/FrontLeft").GetComponent<WheelCollider>();
		myFrontWheelRadius = wheelColliderFrontLeft.radius;
		wheelColliderFrontRight = base.transform.Find("WheelColliders/FrontRight").GetComponent<WheelCollider>();
		wheelColliderRearLeft = base.transform.Find("WheelColliders/RearLeft").GetComponent<WheelCollider>();
		myRearWheelRadius = wheelColliderRearLeft.radius;
		wheelColliderRearRight = base.transform.Find("WheelColliders/RearRight").GetComponent<WheelCollider>();
	}

	public void Move(float h, float v)
	{
		thrust = v;
		steer = h;
	}

	private void Update()
	{
		if (Physics.Raycast(frontLeftWheelTransform.position, -frontLeftWheelTransform.up, out hit, wheelColliderFrontLeft.suspensionDistance + wheelColliderFrontLeft.radius))
		{
			frontLeftWheelTransform.position = hit.point + frontLeftWheelTransform.up * wheelColliderFrontLeft.radius;
		}
		else
		{
			frontLeftWheelTransform.position = base.transform.Find("WheelColliders/FrontLeft").transform.position;
		}
		if (Physics.Raycast(frontRightWheelTransform.position, -frontRightWheelTransform.up, out hit, wheelColliderFrontRight.suspensionDistance + wheelColliderFrontRight.radius))
		{
			frontRightWheelTransform.position = hit.point + frontRightWheelTransform.up * wheelColliderFrontRight.radius;
		}
		else
		{
			frontRightWheelTransform.position = base.transform.Find("WheelColliders/FrontRight").transform.position;
		}
		if (Physics.Raycast(rearLeftWheelTransform.position, -rearLeftWheelTransform.up, out hit, wheelColliderRearLeft.suspensionDistance + wheelColliderRearLeft.radius))
		{
			rearLeftWheelTransform.position = hit.point + rearLeftWheelTransform.up * wheelColliderRearLeft.radius;
		}
		else
		{
			rearLeftWheelTransform.position = base.transform.Find("WheelColliders/RearLeft").transform.position;
		}
		if (Physics.Raycast(rearRightWheelTransform.position, -rearRightWheelTransform.up, out hit, wheelColliderRearRight.suspensionDistance + wheelColliderRearRight.radius))
		{
			rearRightWheelTransform.position = hit.point + rearRightWheelTransform.up * wheelColliderRearRight.radius;
		}
		else
		{
			rearRightWheelTransform.position = base.transform.Find("WheelColliders/RearRight").transform.position;
		}
	}

	private void FixedUpdate()
	{
		myWheelRayCastLocationFront = 0.5f * (frontRightWheelTransform.position + frontLeftWheelTransform.position) - new Vector3(0f, 0.5f, 0f) * myFrontWheelRadius;
		myWheelRayCastLocationRear = 0.5f * (rearRightWheelTransform.position + rearLeftWheelTransform.position) - new Vector3(0f, 0.5f, 0f) * myRearWheelRadius;
		if (Physics.Raycast(myWheelRayCastLocationFront, -base.transform.up, out hit, 1.5f * myFrontWheelRadius) && Physics.Raycast(myWheelRayCastLocationRear, -base.transform.up, out hit, 1.5f * myRearWheelRadius))
		{
			isGrounded = true;
		}
		else
		{
			isGrounded = false;
		}
		if (isGrounded)
		{
			ApplyThrust();
			thrust_myAirMomentum = myCalculatedThrust;
		}
		else
		{
			myAirMomentum = Mathf.SmoothDamp(myAirMomentum, 0f, ref thrust_myAirMomentum, 0.25f);
			physicsBody.velocity += accel * base.transform.forward * myAirMomentum * Time.deltaTime;
			physicsBody.velocity += 20f * -Vector3.up * Time.deltaTime;
		}
		myLocalVelocity = base.transform.InverseTransformDirection(physicsBody.velocity);
		myDrag = Vector3.zero;
		float num = Mathf.Lerp(1f, 5f, traction);
		myDrag.x += myLocalVelocity.x * num;
		myDrag = base.transform.TransformDirection(myDrag);
		physicsBody.velocity -= myDrag * Time.deltaTime;
		myLocalVelocity = base.transform.InverseTransformDirection(physicsBody.velocity);
		currentMPH = myLocalVelocity.z * 2.237f;
		ApplySteering();
		wheelRotationFront = myLocalVelocity.z / myFrontWheelRadius * Time.deltaTime * 57.29578f;
		base.transform.Find("FrontLeftSteering/FrontLeftRotation").transform.Rotate(wheelRotationFront, 0f, 0f);
		base.transform.Find("FrontRightSteering/FrontRightRotation").transform.Rotate(wheelRotationFront, 0f, 0f);
		base.transform.Find("RearLeftSteering/RearLeftRotation").transform.Rotate(wheelRotationFront, 0f, 0f);
		base.transform.Find("RearRightSteering/RearRightRotation").transform.Rotate(wheelRotationFront, 0f, 0f);
	}

	private void ApplyThrust()
	{
		accelerationTime = accelTime;
		accelerationTime = Mathf.Max(0.01f, accelerationTime);
		float num = 0.5f * topSpeedMPH;
		accel = topSpeedMPH;
		if (currentMPH >= topSpeedMPH || currentMPH <= 0f - num)
		{
			accel = 0f;
		}
		if (thrust < 0.1f)
		{
			buildingMomentum = false;
		}
		if (thrust > 0.1f)
		{
			buildingReverseMomentum = false;
		}
		if (thrust < -0.15f && currentMPH > 0.9f * num)
		{
			buildingReverseMomentum = true;
		}
		if (currentMPH < -0.9f * num)
		{
			buildingReverseMomentum = false;
		}
		if (thrust > 0.15f && currentMPH < 0.9f * topSpeedMPH)
		{
			buildingMomentum = true;
		}
		if (currentMPH > 0.9f * topSpeedMPH)
		{
			buildingMomentum = false;
		}
		if (buildingMomentum)
		{
			myCalculatedThrust = Mathf.SmoothDamp(myCalculatedThrust, 1f, ref thrust_CurrentVelocity, accelerationTime);
		}
		else if (buildingReverseMomentum)
		{
			myCalculatedThrust = Mathf.SmoothDamp(myCalculatedThrust, -1f, ref thrust_CurrentVelocity, accelerationTime);
		}
		else
		{
			myCalculatedThrust = thrust;
			thrust_CurrentVelocity = 0f;
		}
		physicsBody.velocity += accel * 2f * base.transform.forward * myCalculatedThrust * Time.deltaTime;
	}

	private void ApplySteering()
	{
		steerAngle = steer * maximumSteeringAngle;
		Quaternion localRotation = base.transform.Find("FrontRightSteering").transform.localRotation;
		Quaternion b = Quaternion.Euler(0f, steerAngle, 0f);
		base.transform.Find("FrontRightSteering").transform.localRotation = Quaternion.Lerp(localRotation, b, 3f * Time.deltaTime);
		localRotation = base.transform.Find("FrontLeftSteering").transform.localRotation;
		base.transform.Find("FrontLeftSteering").transform.localRotation = Quaternion.Lerp(localRotation, b, 3f * Time.deltaTime);
		if (isGrounded && physicsBody.velocity.sqrMagnitude > 0.1f)
		{
			myLocalVelocity = base.transform.InverseTransformDirection(physicsBody.velocity);
			steerAngle *= Mathf.Sign(myLocalVelocity.z);
			Quaternion rhs = Quaternion.Euler(0f, steerAngle * Time.deltaTime * 2f, 0f);
			physicsBody.MoveRotation(base.transform.rotation * rhs);
		}
	}
}
